//
//  SEGHTTPSessionManager.m
//  SEGBasic
//
//  Created by 刘山 on 2018/3/14.
//  Copyright © 2018年 刘山. All rights reserved.
//

#import "SEGHTTPManager.h"
#import "AFNetworking.h"
#import "Reachability.h"
#import <WebKit/WebKit.h>
#import "SEGCommonConfig.h"

NSString * const SEGMimeTypeJPEG = @"image/jpeg";
NSString * const SEGMimeTypeAudio = @"audio/mpeg";
static NSString * const SEGCookie = @"_SEGCookie";
NSString * const kSEGUsualCookie = @"_SEGUsualCookie";

@implementation SEGUploadFileModel
-(instancetype)init{
    if (self == [super init]) {
        _fileName = @"";
        _mimeType = @"";
        _data = [NSData data];
    }
    return self;
}

-(NSString *)name{
    if (!_name) {
        _name = @"file";
    }
    return _name;
}
@end


@interface SEGHTTPManager()
/**
 * 网络请求
 */
@property (nonatomic, strong)AFHTTPSessionManager *manager;
@end

@implementation SEGHTTPManager {
    dispatch_semaphore_t _lock;
}

+ (instancetype)sharedNetworkManager {
    static SEGHTTPManager* instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
    });
    return instance;
}

- (instancetype)init {
    if (self == [super init]) {
        _lock = dispatch_semaphore_create(1);
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
        if (![SEGCommonConfig shared].isAllowNetworkProxy) {
           // 【等保改造】设置代理为空 禁止抓包
           config.connectionProxyDictionary = @{};
        }
        _manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:config];
    }
    return self;
}

- (void)requestWithMethod:(SEGHTTPSessionManagerRequestMethod)method URLString:(NSString*)URLString parameters:(id)parameters finished:(SEGNetworkRequestCallBack)finished{
    dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER);
    self.manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    self.manager.requestSerializer.timeoutInterval = self.timeoutInterval;
    [self segRequestWithMethod:method URLString:URLString parameters:parameters finished:finished];
    dispatch_semaphore_signal(_lock);
}

- (void)requestJSONWithMethod:(SEGHTTPSessionManagerRequestMethod)method URLString:(NSString*)URLString parameters:(id)parameters finished:(SEGNetworkRequestCallBack)finished{
    dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER);
    self.manager.requestSerializer = [AFJSONRequestSerializer serializer];
    self.manager.requestSerializer.timeoutInterval = self.timeoutInterval;
    [self segRequestWithMethod:method URLString:URLString parameters:parameters finished:finished];
    dispatch_semaphore_signal(_lock);
}

-(void)segRequestWithMethod:(SEGHTTPSessionManagerRequestMethod)method URLString:(NSString*)URLString parameters:(id)parameters finished:(SEGNetworkRequestCallBack)finished{
    switch (method) {
        case GET:
        {
            [self.manager GET:URLString parameters:parameters headers:self.headerFields progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                
                // 手动保存cooKie
                [SEGHTTPManager seg_saveCookiesWithURL:[NSURL URLWithString:URLString] httpResponse:task.response];
                finished(responseObject, nil);
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                
                // 手动保存cooKie
                [SEGHTTPManager seg_saveCookiesWithURL:[NSURL URLWithString:URLString] httpResponse:task.response];
                finished(nil, error);
            }];
            break;
            
        }case POST:
        {
            [self.manager POST:URLString parameters:parameters headers:self.headerFields progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                
                // 手动保存cooKie
                [SEGHTTPManager seg_saveCookiesWithURL:[NSURL URLWithString:URLString] httpResponse:task.response];
                finished(responseObject, nil);
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                
                // 手动保存cooKie
                [SEGHTTPManager seg_saveCookiesWithURL:[NSURL URLWithString:URLString] httpResponse:task.response];
                finished(nil, error);
            }];
            break;
        } case DELETE:
        {
            [self.manager DELETE:URLString parameters:parameters headers:self.headerFields success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                
                // 手动保存cooKie
                [SEGHTTPManager seg_saveCookiesWithURL:[NSURL URLWithString:URLString] httpResponse:task.response];
                finished(responseObject, nil);
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                
                // 手动保存cooKie
                [SEGHTTPManager seg_saveCookiesWithURL:[NSURL URLWithString:URLString] httpResponse:task.response];
                finished(nil, error);
            }];
            break;
        }
        default:
            break;
    }
}
/**
 * 上传录音
 * @author Sam
 * @param URLString  图片上传地址
 * @param parameters  其他参数
 * @param recordData  录音数据源
 */
-(void)uploadRecordWithURLString:(NSString *)URLString
                      parameters:(id)parameters
                      recordData:(NSData*)recordData
                        finished:(SEGNetworkRequestCallBackProgress)finished{
    
    [self.manager POST:URLString parameters:parameters headers:self.headerFields constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        [formData appendPartWithFileData:recordData name:@"file" fileName:@"record.mp3" mimeType:@"audio/mpeg"];
        
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        
        finished(PROGRESS,uploadProgress.fractionCompleted, nil,nil);
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        // 手动保存cooKie
        [SEGHTTPManager seg_saveCookiesWithURL:[NSURL URLWithString:URLString] httpResponse:task.response];
        finished(RESULT,0, responseObject,nil);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        // 手动保存cooKie
        [SEGHTTPManager seg_saveCookiesWithURL:[NSURL URLWithString:URLString] httpResponse:task.response];
        finished(RESULT,0,nil,error);
    }];
}

/**
 * 上传多张图片
 * @author Sam
 * @param URLString  图片上传地址
 * @param parameters  其他参数
 * @param imageDataArray  图片集合
 */
-(void)uploadImagesWithURLString:(NSString *)URLString
                      parameters:(id)parameters
                   WithDataArray:(NSArray<NSData*>*)imageDataArray
                        finished:(SEGNetworkRequestCallBackProgress)finished{
    
    
    [self.manager POST:URLString parameters:parameters headers:self.headerFields constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        // 上传 多张图片
        for(NSInteger i = 0; i < imageDataArray.count; i++)
        {
            NSData * imageData = imageDataArray[i];
            
            NSString * fileName = [self segPicRandomName];
            
            [formData appendPartWithFileData:imageData name:@"file" fileName:fileName mimeType:@"image/jpeg"];
        }
        
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        
        finished(PROGRESS,uploadProgress.fractionCompleted, nil,nil);
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        // 手动保存cooKie
        [SEGHTTPManager seg_saveCookiesWithURL:[NSURL URLWithString:URLString] httpResponse:task.response];
        finished(RESULT,0, responseObject,nil);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        // 手动保存cooKie
        [SEGHTTPManager seg_saveCookiesWithURL:[NSURL URLWithString:URLString] httpResponse:task.response];
        finished(RESULT,0,nil,error);
    }];
}

-(void)setTimeoutInterval:(NSTimeInterval)timeoutInterval{
    _timeoutInterval = timeoutInterval;
    
    //self.manager.requestSerializer.timeoutInterval = timeoutInterval;
}

-(void)segNetworkStatus:(SEGNetworkStatusCallBack)block{
    [[AFNetworkReachabilityManager sharedManager] startMonitoring];
    [[AFNetworkReachabilityManager sharedManager]setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        block((SEGNetworkStatus)status);
        return;
    }];
    
    [[AFNetworkReachabilityManager sharedManager] stopMonitoring];
}

- (SEGNetworkStatus)segNetworkStatus {
    Reachability *reachability   = [Reachability reachabilityForInternetConnection];
    NetworkStatus internetStatus = [reachability currentReachabilityStatus];
    SEGNetworkStatus status = SEGNetworkStatusUnknown;
    switch (internetStatus) {
        case ReachableViaWiFi:
            status = SEGNetworkStatusViaWiFi;
            break;
        case ReachableViaWWAN:
            status = SEGNetworkStatusViaWWAN;
            break;
        case NotReachable:
            status = SEGNetworkStatusNotReachable;
            break;
        default:
            break;
    }
    return status;
}

-(void)segCancelAllRequest{
    [self.manager.operationQueue cancelAllOperations];
}

/**
 * 移除所有cookies缓存
 * @author Sam
 */
- (void)removeCookies {
    NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    NSArray *cookies = [NSArray arrayWithArray:[cookieJar cookies]];
    for (NSHTTPCookie *cookie in cookies) {
        [cookieJar deleteCookie:cookie];
    }
    if (@available(iOS 9.0, *)) {
        NSSet *websiteDataTypes = [WKWebsiteDataStore allWebsiteDataTypes];
        NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0];
        [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:^{
        }];
    }
    if ([SEGCommonConfig shared].isCloseManualCookie == NO) {
        /// 移除自管理的cookie
        NSDictionary *keyDict = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation];
        for (NSString *key in keyDict) {
            // 老版本cookie, 根据host为key存储
            if ([key containsString:SEGCookie]) [[NSUserDefaults standardUserDefaults] removeObjectForKey:key];
        }
        // 新版本只有一个key, 全局共同cookie
        [[NSUserDefaults standardUserDefaults] removeObjectForKey:kSEGUsualCookie];
    }
}

/// 手动保存cookie
/// @param url cookie所属url
/// @param response 响应体
+ (void)seg_saveCookiesWithURL:(NSURL *)url httpResponse:(NSURLResponse *)response {
    if ([SEGCommonConfig shared].isCloseManualCookie) return;
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
    NSDictionary *cookieDict = [[NSUserDefaults standardUserDefaults] objectForKey:kSEGUsualCookie];
    NSMutableDictionary *mCookieDict = [NSMutableDictionary dictionaryWithDictionary:cookieDict];
    // 兼容老版本cookie, 根据host为key存储
    if (!mCookieDict || mCookieDict.allKeys.count == 0) {
        NSString *storeKey = [NSString stringWithFormat:@"%@%@", url.host, SEGCookie];
        NSDictionary *tempCookieDict = [[NSUserDefaults standardUserDefaults] objectForKey:storeKey];
        mCookieDict = [NSMutableDictionary dictionaryWithDictionary:tempCookieDict];
    }
    NSArray *cookieArr = [NSHTTPCookie cookiesWithResponseHeaderFields:[httpResponse allHeaderFields] forURL:url];
    [cookieArr enumerateObjectsUsingBlock:^(NSHTTPCookie *cookie, NSUInteger idx, BOOL * _Nonnull stop) {
        [mCookieDict setObject:cookie.value forKey:cookie.name];
    }];
    [[NSUserDefaults standardUserDefaults] setObject:mCookieDict forKey:kSEGUsualCookie];
}

/// 获取本地cookie
/// @param url cookie所属url
+ (NSString *)seg_getCookiesDictionaryWithURL:(NSURL *)url {
    if ([SEGCommonConfig shared].isCloseManualCookie) return nil;
    __block NSString *_cookieStr = @"";
    NSDictionary *cookieDict = [[NSUserDefaults standardUserDefaults] objectForKey:kSEGUsualCookie];
    // 兼容老版本cookie, 根据host为key存储
    if (!cookieDict || cookieDict.allKeys.count == 0) {
        NSString *storeKey = [NSString stringWithFormat:@"%@%@", url.host, SEGCookie];
        cookieDict = [[NSUserDefaults standardUserDefaults] objectForKey:storeKey];
    }
    [cookieDict enumerateKeysAndObjectsUsingBlock:^(NSString *name, NSString *value, BOOL * _Nonnull stop) {
        NSString *str = [NSString stringWithFormat:@"%@=%@; ", name, value];
        _cookieStr = [_cookieStr stringByAppendingString:str];
    }];
    return _cookieStr;
}

- (void)segAddHttpHearders {
    [self.headerFields enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        [self.manager.requestSerializer setValue:obj forHTTPHeaderField:key];
    }];
}

-(void)uploadVoicesWithURLString:(NSString*)urlString parameters:(id)parameters sources:(NSArray<NSData*>*)sources progress:(void(^)(double progressValue))progress  completed:(void (^) (id result,NSError * error))completed{
    
    NSMutableArray <SEGUploadFileModel*>*tmp = [NSMutableArray array];
    for (NSData *object in sources) {
        SEGUploadFileModel *data = [SEGUploadFileModel new];
        data.data = object;
        data.fileName = [self segPicRandomNameWithType:@"mp3"];
        data.mimeType = SEGMimeTypeAudio;
        [tmp addObject:data];
    }
    
    [self uploadDatasWithURLString:urlString parameters:parameters sources:tmp progress:progress completed:completed];
}

-(void)uploadVoiceWithURLString:(NSString*)urlString parameters:(id)parameters source:(NSData*)source fileName:(NSString*)fileName progress:(void(^)(double progressValue))progress  completed:(void (^) (id result,NSError * error))completed{
    SEGUploadFileModel *data = [SEGUploadFileModel new];
    data.data = source;
    data.fileName = fileName;
    data.mimeType = SEGMimeTypeAudio;
    
    [self uploadDatasWithURLString:urlString parameters:parameters sources:@[data] progress:progress completed:completed];
}

-(void)uploadVoiceWithURLString:(NSString*)urlString parameters:(id)parameters source:(NSData*)source progress:(void(^)(double progressValue))progress  completed:(void (^) (id result,NSError * error))completed{
    [self uploadVoiceWithURLString:urlString parameters:parameters source:source fileName:[self segPicRandomNameWithType:@"mp3"] progress:progress completed:completed];
}

-(void)uploadImageWithURLString:(NSString*)urlString parameters:(id)parameters source:(NSData*)source fileName:(NSString*)fileName progress:(void(^)(double progressValue))progress  completed:(void (^) (id result,NSError * error))completed{
    SEGUploadFileModel *data = [SEGUploadFileModel new];
    data.data = source;
    data.fileName = fileName;
    data.mimeType = SEGMimeTypeJPEG;
    
    [self uploadDatasWithURLString:urlString parameters:parameters sources:@[data] progress:progress completed:completed];
}

-(void)uploadImageWithURLString:(NSString*)urlString parameters:(id)parameters source:(NSData*)source progress:(void(^)(double progressValue))progress  completed:(void (^) (id result,NSError * error))completed{
    [self uploadImageWithURLString:urlString parameters:parameters source:source fileName:[self segPicRandomName] progress:progress completed:completed];
}

-(void)uploadImagesWithURLString:(NSString*)urlString parameters:(id)parameters sources:(NSArray<NSData*>*)sources progress:(void(^)(double progressValue))progress  completed:(void (^) (id result,NSError * error))completed{
    
    NSMutableArray <SEGUploadFileModel*>*tmp = [NSMutableArray array];
    for (NSData *object in sources) {
        SEGUploadFileModel *data = [SEGUploadFileModel new];
        data.data = object;
        data.fileName = [self segPicRandomName];
        data.mimeType = SEGMimeTypeJPEG;
        [tmp addObject:data];
    }
    
    [self uploadDatasWithURLString:urlString parameters:parameters sources:tmp progress:progress completed:completed];
}

/**
 上传数据到服务器
 
 @author Sam
 @param urlString 服务地址
 @param parameters 上传参数
 @param sources 数据源
 @param progress 上传进度
 @param completed 完成回调
 */
-(void)uploadDatasWithURLString:(NSString*)urlString parameters:(id)parameters sources:(NSArray<SEGUploadFileModel*>*)sources progress:(void(^)(double progressValue))progress  completed:(void (^) (id result,NSError * error))completed{
    [self.manager POST:urlString parameters:parameters headers:self.headerFields constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        for (SEGUploadFileModel *object in sources) {
            [formData appendPartWithFileData:object.data name:object.name fileName:object.fileName mimeType:object.mimeType];
        }
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        if (progress) {
            progress(uploadProgress.fractionCompleted);
        }
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        // 手动保存cooKie
        [SEGHTTPManager seg_saveCookiesWithURL:[NSURL URLWithString:urlString] httpResponse:task.response];
        completed(responseObject,nil);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        // 手动保存cooKie
        [SEGHTTPManager seg_saveCookiesWithURL:[NSURL URLWithString:urlString] httpResponse:task.response];
        completed(nil,error);
    }];
}


/**
 * 图片随机的名称
 * @author Sam
 */
-(NSString*)segPicRandomName{
    return  [self segPicRandomNameWithType:@"png"];
}

-(NSString*)segPicRandomNameWithType:(NSString*)type{
    
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.dateFormat =@"yyyyMMddHHmmss";
    NSString *str = [formatter stringFromDate:[NSDate date]];
    
    int random =100000 +  (arc4random() % 100001);
    
    // 上传的参数名
    NSString *Name = [NSString stringWithFormat:@"%@%d", str , random];
    
    // 上传filename
    return [NSString stringWithFormat:@"%@.%@", Name,type];
}
 
@end



















